package com.bjtu.ptsite.service.impl;

import com.bjtu.ptsite.mapper.FollowMapper;
import com.bjtu.ptsite.mapper.UserMapper;
import com.bjtu.ptsite.model.PageResult;
import com.bjtu.ptsite.model.User;
import com.bjtu.ptsite.model.UserDTO;
import com.bjtu.ptsite.service.UserService;
import com.bjtu.ptsite.tracker.entity.TrackerMessage;
import com.bjtu.ptsite.utils.EmailUtil;
import com.bjtu.ptsite.utils.UUIDUtils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 *
 * @author Zehao Wang, Junjie Zhang, Yutao Wei
 *
 */
@Service
public class UserServImpl implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private FollowMapper followMapper;
    @Autowired
    private EmailUtil emailUtil;
    private final ConcurrentHashMap<String, String> emailCodes = new ConcurrentHashMap<>();
    private static final long CODE_EXPIRE_MINUTES = 60;
    private static double threshould = 1.2;
    /**100MB*/
    private static long LEVEL_1 = 100000000L;
    /**1GB*/
    private static long LEVEL_2 = 1000000000L;
    /**10GB*/
    private static long LEVEL_3 = 10000000000L;
    /**100GB*/
    private static long LEVEL_4 = 100000000000L;
    /**1TB*/
    private static long LEVEL_5 = 1000000000000L;
    private static final int CODE_PARTS_LENGTH = 2;
    //每日登录积分
    private static int DailyAward = 10;

    private static final BigDecimal RISK_THRESHOLD = new BigDecimal("0.4"); // 风险阈值 20%
    private static final long UPLOAD_THRESHOLD = 10737418240L;// 10GB
    private static final int ASSESS_DAY = 30;// 考核周期天数
    private static final int CONSECUTIVE_DAYS_LIMIT = 7; // 连续天数限制
    private static final String ROLE_ADMINISTRATOR = "admin";

    @Override
    public User login(User user) {
        return userMapper.login(user);
    }

    @Override
    public boolean isUsernameExists(String username) {
        return userMapper.selectByUsername(username) != null;
    }

    @Override
    public boolean isEmailExists(String email) {
        return userMapper.selectByEmail(email) != null;
    }

    @Override
    public void register(User user) {
        // 生成唯一默认用户名
        String username;
        do {
            username = generateDefaultUsername(user.getEmail());
        } while (isUsernameExists(username));

        String passKey;
        passKey = UUIDUtils.generateUUID();
        user.setPassKey(passKey);
        user.setUsername(username);
        user.setRegistrationDate(LocalDateTime.now().format(
                DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        userMapper.insertUser(user);
    }

    @Override
    public void sendVerificationCode(String email, int request) {
        String code = generateRandomCode();
        emailUtil.sendVerificationEmail(email, code, request);
        emailCodes.put(email, code + "|" + (System.currentTimeMillis() + CODE_EXPIRE_MINUTES * 60 * 1000));
    }

    @Override
    public boolean verifyCode(String email, String inputCode) {
        String stored = emailCodes.get(email);
        if (stored == null) {
            return false;
        }

        String[] parts = stored.split("\\|");
        if (parts.length != CODE_PARTS_LENGTH) {
            return false;
        }

        String code = parts[0];
        long expireTime = Long.parseLong(parts[1]);
        if (System.currentTimeMillis() <= expireTime && code.equals(inputCode)) {
            emailCodes.remove(email);
            return true;
        }
        ;
        return false;
    }

    private String generateRandomCode() {
        return String.format("%06d", new Random().nextInt(999999));
    }

    private String generateDefaultUsername(String email) {
        String prefix = email.split("@")[0];
        return "user_" + prefix + "_" + String.format("%04d", new Random().nextInt(9999));
    }

    @Override
    public User getUserById(int userId) {
        return userMapper.selectById(userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public User updateUserProfile(Integer userId, UserDTO updateDTO) {
        // 验证用户存在性
        User existingUser = userMapper.selectById(userId);
        if (existingUser == null) {
            throw new RuntimeException("用户不存在");
        }

        // 构建更新对象
        User updateUser = userMapper.selectById(userId);
        updateUser.setUsername(updateDTO.getUsername());
        updateUser.setAddress(updateDTO.getAddress());

        // 执行更新
        userMapper.updateUserSelective(updateUser);

        // 返回更新后的完整用户对象
        return userMapper.selectById(userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean resetPassword(int userId, String newPassword) {
        userMapper.updatePassword(userId, newPassword);
        return true;
    }

    @Override
    public void updateUserTraffic(String passKey, long uploadedDelta, long downloadedDelta) {
        userMapper.updateUserTraffic(passKey, uploadedDelta, downloadedDelta);
    }

    @Override
    public void updateAvatar(int userId, String avatarUrl) {
        User user = new User();
        user.setUserId(userId);
        user.setAvatar(avatarUrl);
        userMapper.updateAvatar(user);
    }

    @Override
    public String getAvatarById(int userId) {
        String curAvatar = userMapper.selectAvatarById(userId);
        return curAvatar;
    }

    @Override
    public void followUser(int curUserId, int userId) {
        followMapper.insertFollow(curUserId, userId);
        userMapper.addFollows(curUserId);
        userMapper.addFans(userId);
    }

    @Override
    public void deFollowUser(int curUserId, int userId) {
        followMapper.deleteFollow(curUserId, userId);
        userMapper.deFollows(curUserId);
        userMapper.deFans(userId);
    }

    @Override
    public boolean isFollowExits(int curUserId, int userId) {
        if (followMapper.selectFollow(curUserId, userId) == 0) {
            return false;
        }
        ;
        return true;
    }

    @Override
    public List<UserDTO> getFollows(int userId) {
        List<UserDTO> follows = null;
        follows = userMapper.getFollows(userId);
        return follows;
    }

    @Override
    public List<UserDTO> getFans(int userId) {
        List<UserDTO> fans = null;
        fans = userMapper.getFans(userId);
        return fans;
    }

    @Override
    public void upgradeQualifiedUsers() {
        List<User> users = userMapper.findQualified(threshould);
        users.stream()
                .forEach(user -> {
                    int newLevel = addLevel(user);
                    userMapper.updateLevel(user.getUserId(), newLevel);
                });
    }

    private int addLevel(User user) {
        if (user.getUploadedDelta() >= LEVEL_1) {
            return 1;
        } else if (user.getUploadedDelta() >= LEVEL_2) {
            return 2;
        } else if (user.getUploadedDelta() >= LEVEL_3) {
            return 3;
        } else if (user.getUploadedDelta() >= LEVEL_4) {
            return 4;
        } else if (user.getUploadedDelta() >= LEVEL_5) {
            return 5;
        } else {
            return 0;
        }
    }

    @Override
    public void banUser(int userId) {
        userMapper.banUser(userId);
    }

    @Override
    public void unbanUser(int userId) {
        userMapper.unbanUser(userId);
    }

    public void updateUserTraffic2(User user) {
        userMapper.updateUserTraffic1(user);
    }

    @Override
    public PageResult<User> getUserList(int page, int size) {
        // 计算分页偏移量
        int offset = (page - 1) * size;

        // 分页查询
        List<User> users = userMapper.selectUsersByPage(offset, size);

        users.stream().map(user -> {
            user.setPassword(null);// 过滤密码信息
            return user;
        }).collect(Collectors.toList());

        // 获取总记录数
        int total = userMapper.selectTotalCount();

        return new PageResult<>(total, users);
    }

    @Override
    public void countSharingRate() {
        List<User> users = userMapper.selectUserALL();
        users.stream().map(user -> {
            BigDecimal up = BigDecimal.valueOf(user.getUploadedDelta());
            BigDecimal down = BigDecimal.valueOf(user.getDownloadedDelta());
            if (down == BigDecimal.valueOf(0)) {
                user.setSharingRate(BigDecimal.valueOf(0));
            } else {
                BigDecimal shareRate = up.divide(down, 4, RoundingMode.HALF_UP);
                user.setSharingRate(shareRate);
            }
            if (user.getSharingRate().compareTo(RISK_THRESHOLD) == -1) {
                user.setUnactivateDay(user.getUnactivateDay() + 1);
                userMapper.updateUserSelective(user);
            } else {
                user.setUnactivateDay(0);
                userMapper.updateUserSelective(user);
            }
            userMapper.updateUserSelective(user);
            return user;
        }).collect(Collectors.toList());
    }

    @Override
    public void dailyAward(User user) {
        user.setDailyAward(false);
        user.setSeedPoints(user.getSeedPoints() + DailyAward);
        userMapper.updateUserSelective(user);
    }

    @Override
    public void resetDailyAward() {
        List<User> users = userMapper.selectUserALL();
        users.stream().map(user -> {
            user.setDailyAward(true);
            userMapper.updateUserSelective(user);
            return user;
        }).collect(Collectors.toList());
    }

    @Override
    public void dailyAssess() {
        List<User> users = userMapper.selectUserALL();
        for (User user : users) {
            if (!user.getRole().equals(ROLE_ADMINISTRATOR) && !user.isBaned()) {
                if (user.getUnactivateDay() == CONSECUTIVE_DAYS_LIMIT) {
                    banUser(user.getUserId());
                    return;
                }
                if (user.getAssessDay()==0) {
                    if(user.getUploadAssess() < UPLOAD_THRESHOLD){
                        banUser(user.getUserId());
                        return;
                    }
                    else{
                        user.setAssessDay(ASSESS_DAY);
                        user.setUploadAssess(0L);
                    }
                }
                else{
                    user.setAssessDay(user.getAssessDay()-1);
                }
                userMapper.updateUserSelective(user);
            }
        }
    }
}
